package com.mew.common.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scripting.support.ResourceScriptSource;

import java.time.Duration;

/**
 * @Author King.Song
 * @Date 2020/5/18 0018
 **/
@Configuration
@Slf4j
public class RedisSourceConfiguration {


    @Bean
    public GenericObjectPoolConfig genericObjectPoolConfig(RedisSourceProperties redisSourceProperties) {
        GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
        genericObjectPoolConfig.setMaxIdle(redisSourceProperties.getMaxIdle());
        genericObjectPoolConfig.setMinIdle(redisSourceProperties.getMinIdle());
        genericObjectPoolConfig.setMaxTotal(redisSourceProperties.getMaxActive());
        genericObjectPoolConfig.setMaxWaitMillis(redisSourceProperties.getMaxWait());
        return genericObjectPoolConfig;
    }

    @Bean
    public LettuceConnectionFactory lettuceConnectionFactory(GenericObjectPoolConfig genericObjectPoolConfig, RedisSourceProperties redisSourceProperties) {
        // click
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setDatabase(redisSourceProperties.getDatabase());
        redisStandaloneConfiguration.setHostName(redisSourceProperties.getHost());
        redisStandaloneConfiguration.setPort(redisSourceProperties.getPort());
        redisStandaloneConfiguration.setPassword(RedisPassword.of(redisSourceProperties.getPassword()));
        // Cluster
//        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
//        String[] serverArray = clusterNodes.split(",");
//        Set<RedisNode> nodes = new HashSet<RedisNode>();
//        for (String ipPort : serverArray) {
//            String[] ipAndPort = ipPort.split(":");
//            nodes.add(new RedisNode(ipAndPort[0].trim(), Integer.valueOf(ipAndPort[1])));
//        }
//        redisClusterConfiguration.setPassword(RedisPassword.of(password));
//        redisClusterConfiguration.setClusterNodes(nodes);
//        redisClusterConfiguration.setMaxRedirects(maxRedirects);
        LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
                .commandTimeout(Duration.ofMillis(redisSourceProperties.getTimeout()))
                .poolConfig(genericObjectPoolConfig)
                .build();
//        if (redisSourceProperties.getSsl()){
//            clientConfig.isUseSsl();
//        }
        LettuceConnectionFactory factory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfig);
        return factory;
    }

    @Bean
    public RedisTemplate<String, Object> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory){

        RedisTemplate<String, Object> template = new RedisTemplate<>();
        GenericJackson2JsonRedisSerializer valueSerializer = new GenericJackson2JsonRedisSerializer();
        StringRedisSerializer keySerializer = new StringRedisSerializer();

        template.setConnectionFactory(redisConnectionFactory);
        template.setDefaultSerializer(valueSerializer);

        template.setKeySerializer(keySerializer);
        template.setValueSerializer(valueSerializer);

        template.setHashKeySerializer(valueSerializer);
        template.setHashValueSerializer(valueSerializer);

        return template;
    }

// Reactive   @Bean
//    public ReactiveRedisTemplate<String, Object> reactiveRedisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
//        RedisSerializer<String> keySerializer = new StringRedisSerializer();
//        RedisSerializer<Object> valueSerializer = new GenericJackson2JsonRedisSerializer();
//        RedisSerializationContext<String, Object> serializationContext = RedisSerializationContext.<String, Object>newSerializationContext()
//                .key(keySerializer)
//                .value(valueSerializer)
//                .hashKey(valueSerializer)
//                .hashValue(valueSerializer).build();
//        return new ReactiveRedisTemplate<String, Object>(lettuceConnectionFactory, serializationContext);
//    }


    @Bean
    public CacheManager cacheManager(LettuceConnectionFactory lettuceConnectionFactory) {
        return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(lettuceConnectionFactory).build();
    }

    @Bean(name = "jackpotScript")
    public DefaultRedisScript<Long> jackpotScript() {
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setResultType(Long.class);
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("scripts/roomprofile-jackpot.lua")));
        return redisScript;
    }

    @Bean(name = "profileScript")
    public DefaultRedisScript<Long> profileScript() {
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setResultType(Long.class);
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("scripts/uprofile.lua")));
        return redisScript;
    }

    @Bean(name = "controlRoomScript")
    public DefaultRedisScript<Long> controlRoomScript() {
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setResultType(Long.class);
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("scripts/room-control.lua")));
        return redisScript;
    }

    @Bean(name = "roomProfileScript")
    public DefaultRedisScript<Long> roomProfileScript() {
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setResultType(Long.class);
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("scripts/roomprofile.lua")));
        return redisScript;
    }



    @Bean
    public RedisMessageListenerContainer container(LettuceConnectionFactory lettuceConnectionFactory) {

        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(lettuceConnectionFactory);
        return container;
    }




}
